#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"

// 定义蜂鸣器端口位
sbit Buzzer=P2^5;

// 定义宏播放速度，值为四分音符的时长(ms)
#define SPEED   500

// 定义重装载值数组
unsigned int code ReloadValues[]={
    // 索引是从1开始的，这里空出一位
    0,
    // 低音
    63618,63721,63825,63918,64011,64093,64175,64250,64321,64390,64453,64514,
    // 中音
    64570,64623,64674,64722,64767,64810,64850,64888,64924,64958,64990,65020,
    // 高音
    65048,65075,65100,65124,65147,65168,65188,65207,65225,65242,65258,65273
};

// 定义小星星数组
// code 代表的是 把定义的数据表存储到 flash 存储器中，否则存储到 RAM 中
// 51单片机的 RAM 通常都比较小，1k 左右，对于小量的数据是可以存储到RAM中，如果是声音文件等大数据需要存储到 FLASH 存储器中
unsigned char code TwinkleTwinkleLittleStar[]={
    // 一闪一闪亮晶晶
    13,4,
    13,4,
    20,4,
    20,4,
    22,4,
    22,4,
    20,4+4,
    // 满天都是小星星
    18,4,
    18,4,
    17,4,
    17,4,
    15,4,
    15,4,
    13,4+4,
    // 终止符测试
    0,4,
    // 挂在天上放光明
    20,4,
    20,4,
    18,4,
    18,4,
    17,4,
    17,4,
    15,4+4,
    // 好像许多小眼睛
    20,4,
    20,4,
    18,4,
    18,4,
    17,4,
    17,4,
    15,4+4,
    // 结束标记
    0xFF
};

// 定义数组索引等
unsigned char ReloadValues_Index, TwinkleTwinkleLittleStar_Index, DurationBasics;

void main()
{
    Timer0_Init();
    while(1)
    {
        if (ReloadValues_Index != 0xFF)
        {
            // 选择音符对应的频率
            ReloadValues_Index = TwinkleTwinkleLittleStar[TwinkleTwinkleLittleStar_Index];  // 重载值索引
            TwinkleTwinkleLittleStar_Index++;
            // 选择音符对应的时值
            DurationBasics = TwinkleTwinkleLittleStar[TwinkleTwinkleLittleStar_Index];      // 时长基数
            TwinkleTwinkleLittleStar_Index++;
            Delay(SPEED / 4 * DurationBasics);
            
            // 音符间短暂停顿
            TR0 = 0;
            Delay(5);
            TR0 = 1;
        }
        else
        {
            TR0 = 0;
            while(1);
        }
    }
}

/**
  * @brief 定时器0终端执行程序
  * @param  无
  * @retval 无
  */
void Timer0_Routine() interrupt 1
{
    unsigned int ReloadValue = ReloadValues[ReloadValues_Index];
    
    // 如果不是休止符
    if (ReloadValue)
    {
        TL0 = ReloadValue%256;
        TH0 = ReloadValue/256;
        
        // 翻转蜂鸣器IO口
        Buzzer=!Buzzer;
    }

}